【クリスマスだし】Internet Explorerとうまく付き合う方法【IE対応まとめ】【25日目の6】
こんばんは、クラスメソッドWebマスターの野中です。
今日はクリスマスですね、社内には独り身の負のオーラが満ちてます(既婚者が多いので残っている人は少ない)。
ところで、最近はCSS3もすこしずつ使えるようになってきていて、IE6からIE8の対応を蔑ろにしてしまっている自分がいます。
Web制作に携わってから6年、常に付きまとう古いIEは腐れ縁というか、ある意味青春ですね。
とっても今さら感たっぷりなお題目ですが、ここでIE対応のポイントを自分のために総浚いして青春に決着をつけたいと思います。
過去の経験と情報収集をもとにまとめているので実際にテストしたものではありません。
解決のきっかけ程度になれば良いと思いまとめています。
- IEの現状
- 一般的なブラウザと先進的なブラウザに対する手法と考え方
- ドキュメントタイプ:文書型定義
- IE向け条件付きコメントで分岐処理
- CSSハック
- CSSレイアウト系のバグ
- IE6,7,8でHTML5を使う
- IE6,7,8でCSS3を使う
- IE6,7,8でMedia Queries対応
- IE6でPNG対応
- IE6,7,8でSVG
- IE6,7,8でCanvas
- IE6,7でWeb Font
- まとめ
IEの現状
今年1年間のシェアをStatCounterで調べてみました。
「OS別シェア」「ブラウザー別シェア」「ブラウザーバージョン別シェア」「おまけモバイルブラウザ別シェア」のグラフです。
OSではWindows系が圧倒的ですね。
IE9のシェアが高いので少しほっとします。IE6はさすがに1%となっていますが、まだまだIE8のシェアも高いようです。
一般的なブラウザと先進的なブラウザに対する手法と考え方
一般的でシェアの高いブラウザと先進的で高機能なブラウザに対してどのような基準で体験を提供していくかとても悩むところです。
最近では、以下にあげる3つの考え方があるようです。
プログレッシブ エンハンスメント(Progressive Enhancement)
一般的なブラウザを基準に先進的なブラウザにはより良い体験を提供するという考え方です。
グレイスフル デグラデーション(Graceful Degradation)
プログレッシブ エンハンスメントとは逆に、先進的なブラウザを基準に、一般的(または古い)ブラウザにはレベルを落とした体験を提供するという考え方です。
ポリフィル(Polyfill)
先進的なブラウザを基準にし、一般的(または古い)ブラウザを独自実装などを駆使し先進的なブラウザに近づけるというすべてのブラウザに近い体験を提供しようという考え方です。
ポリフィルを実現するためには独自の拡張を多様することにもなり、古いブラウザの場合負荷が高くなることがあります。
これによるパフォーマンスへの影響も考慮が必要です。
参考:
ドキュメントタイプ:文書型定義(DOCTYPE、DTD)
言わずもがな、DOCTYPEってこれのことです。
<!-- HTML5 --> <!DOCTYPE html>
ドキュメントタイプは「互換モード(Quirks mode)」と「標準モード(Standards mode)」に別れ、レンダリングモードに影響します。
互換モードは過去の古いブラウザ向けのレンダリングモード、標準モードはCSSの標準に準拠して表示するモードです。
必要あるの?
DOCTYPEを書かないと一般的なブラウザでは互換モードと認識され、CSSのレンダリングが意図しない表示になります。
標準モードでレンダリングさせたい場合は必ずDOCTYPEを記述しましょう。
DOCTYPEの種類
DTD | サンプル | IE6 | IE7以上 |
---|---|---|---|
- | - | 互換 | 互換 |
HTML4.01 Frameset | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"> | 互換 | 互換 |
HTML4.01 Frameset | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"> | 標準 | 標準 |
HTML4.01 Transitional | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | 互換 | 互換 |
HTML4.01 Transitional | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | 標準 | 標準 |
HTML4.01 Strict | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> | 標準 | 標準 |
HTML4.01 Strict | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> | 標準 | 標準 |
XHTML1.0 Frameset | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd" /> | 標準 | 標準 |
XHTML1.0 Frameset | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd" /> |
互換 | 標準 |
XHTML1.0 Transitional | <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" /> | 標準 | 標準 |
XHTML1.0 Transitional | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" /> |
互換 | 標準 |
XHTML1.0 Strict | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" /> | 標準 | 標準 |
XHTML1.0 Strict | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" /> |
互換 | 標準 |
XHTML5 | <!DOCTYPE html> | 標準 | 標準 |
XML宣言をすると互換モード(IE6のみ)
IE6はDOCTYPEから始まっていないと互換モードとなります。なので一番最初に入れるXML宣言があると互換モードとなってしまいます。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
メタタグを使った標準モードの強制指定(IE8以上)
IE8からメタタグを使い標準モードを強制指定できるようになりました。これはDOCTYPE宣言よりも優先されます。
<meta http-equiv="X-UA-Compatible" content="IE=8" />
content="IE=x"(content属性)で詳細なモードを指定することができます。
- content="IE=5"………互換モード
- content="IE=7"………IE7標準モード
- content="IE=8"………IE8標準モード
- content="IE=EmulateIE7"………Windows Internet Explorer 7 と同様の動作を行うDOCTYPEによる制御
- content="IE=EmulateIE8"………Windows Internet Explorer 8 と同様の動作を行うDOCTYPEによる制御
- content="IE=edge"………最も互換性の高いモード
参考サイト
- 標準モードと互換モードについて
- META タグと将来の互換性のロック
- HTML5 の DOCTYPE 宣言って IE6 でも標準モードになるんですね
- DOCTYPE|HTML5タグリファレンス
- DOCTYPEスイッチ
IE向け条件付きコメントで分岐処理(IE Conditional Comments)
インターネットエクスプローラー(以降IE)で独自実装されている条件付きコメントは、スタイルシートやスクリプト、HTMLなどの表示をHTMLのみで振り分けられる便利なものです。これが無ければIEへの対応に多くのコストがかかっていたかもしれません。
すべてのIEにのみ対応
<!--[if IE]> <p>このブラウザはIEです。</p> <![endif]-->
IE 6にのみ対応
<!--[if IE 6]> <p>このブラウザはIE6です。</p> <![endif]-->
IE 7にのみ対応
<!--[if IE 7]> <p>このブラウザはIE7です。</p> <![endif]-->
IE 8にのみ対応
<!--[if IE 8]> <p>このブラウザはIE8です。</p> <![endif]-->
IE9以上、とその他のブラウザに対応
<!--[if (gt IE 9)|!(IE)]><!--> <p>このブラウザはIE9以上かその他のブラウザです。</p> <!--<![endif]-->
bodyタグにバージョン用のクラスを指定する
IE Conditional Commentsを使うことで、後述するIEハックに頼らずCSSの振り分けを行うことができます。
<!--[if lt IE 7 ]> <body class="ie6"> <![endif]--> <!--[if IE 7 ]> <body class="ie7"> <![endif]--> <!--[if IE 8 ]> <body class="ie8"> <![endif]--> <!--[if IE 9 ]> <body class="ie9"> <![endif]--> <!--[if (gt IE 9)|!(IE)]><!--> <body id="body" class="modern"> <!--<![endif]-->
参考サイト
CSSハック
以下で紹介するハックはブラウザの標準モードを基準とした各バージョン用のハックです(IE6以下を気にすることはほとんどないので記載しません)。
後方互換モードだとハックが適用されないものもあるので注意してください。
IE6,7,8
IEの全バージョンを対象としたハックです。
セレクタハック(除外系)
W3C CSS Validatorも通るハックです。対象のセレクタの前に「:root 」を付けます。 この指定がされた場合、すべてのIEには適用されなくなります。
:root .sample { background: #000; }
@importハック
詳しく解説された記事がこちらにあるので参考になると思います。
IE6
IE6向けのハックです。
アンダースコアハック
W3C CSS ValidatorではErrorとなるため非推薦のハックです。
プロパティの前にアンダースコア「_」を付けることでIE6のみに対応させることができます。
.sample { _background: #000; }
2スターハック
W3C CSS ValidatorではErrorとなるため非推薦のハックです。対象セレクタの前に「* html*」を付けます。
* html*.sample { background: #000; }
スターハック
W3C CSS Validatorも通るハックです。対象のセレクタの前に「* html 」を付けます。
* html .sample { background: #000; }
!importantハック
W3C CSS Validatorも通るハックです。対象を2重に指定し、前のプロパティに「!important」を付けます。
IE6だけimportantの解釈が違うため、後の指定を適用します。
* html .sample { background: #333!important; background: #000; /* IE6にはこちらが適用 */ }
The Owen Hack(除外系)
W3C CSS Validatorも通るハックです。対象のセレクタの前に「head:first-child+body 」を付けるとIE6が除外されます。
head:first-child+body .sample { background: #333; }
セレクタハック(除外系)
W3C CSS Validatorも通るハックです。対象のセレクタの前に「html>body 」または「head+body 」を付けます。
この指定がされた場合、IE6には適用されなくなります。
html>body .sample { background: #000; } head+body .sample { background: #000; }
属性セレクタハック(除外系)
W3C CSS Validatorも通るハックです。対象のセレクタの前に「html[xmlns]>/**/body 」または、「html[lang='\ja'] 」を付けます。 この指定がされた場合、すべてのIEには適用されなくなります。
html[xmlns]>/**/body .sample { background: #000; } html[lang='\ja'] .sample { background: #000; }
コメントハック(除外系)
W3C CSS Validatorも通るハックです。対象のプロパティのバリューの前に「/**/」を付けます。
この指定がされた場合、IE6には適用されなくなります。
* html .sample { background: /**/#000; }
属性セレクタハック
W3C CSS Validatorも通るハックです。対象のセレクタの前に「html[xmlns] 」を付けます。
この指定がされた場合、IE6には適用されなくなります。
html[xmlns] .sample { background: #000; }
IE6 and IE7
IE6及び、IE7どちらにも適用されるハックです。
ハッシュハック
W3C CSS ValidatorではErrorとなるため非推薦のハックです。
プロパティの前に「#」を付けることですべてのIE6,7のみに対応させることができます。
.sample { #background: #000; }
アスタリスクハック
W3C CSS ValidatorではErrorとなるため非推薦のハックです。
プロパティの前にアスタリスク「*」を付けることですべてのIEのみに対応させることができます。
ご指摘をいただいたので修正いたしました。
.sample { *background: #000; }
スター7ハック
W3C CSS ValidatorではErrorとなるため非推薦のハックです。対象のセレクタの前に「html*」を付けます。
html*.sample { background: #000; }
スラッシュハック
W3C CSS ValidatorではErrorとなるため非推薦のハックです。対象のプロパティの前にスラッシュ「/」を付けます。
.sample { /background: #000; }
IE7
IE7向けのハックです。
スター+ハック
W3C CSS Validatorも通るハックです。対象のセレクタの前に「*+html 」を付けます。
*+html .sample { background: #000; }
IE7スターハック
W3C CSS Validatorも通るハックです。対象のセレクタの前に「*:first-child+html 」を付けます。
*:first-child+html .sample { background: #000; }
IE6,7,8,9
\9ハック
対象のバリューの最後に「\9」を付けます。
.sample { background: #000\9; }
IE9
IE9向けのハックです。
対象のセレクタの前に「:root 」、バリューの最後に「 \0/」を付けます。
:root .sample { background: #000 \0/; }
\9ハック
または、セレクタの前に「:not(:target) 」を付けプロパティの最後に「 \9」付けるものもあります。
:not(:target) .sample { background: #000\9; }
参考サイト
CSSレイアウト系のバグ
解決方法
0,描画モードの違い
IEには標準準拠モードと互換モードがあります。
この違いによるレイアウト崩れもよくあるので、この記事の初めて紹介したDOCTYPE宣言について確認しましょう。
1,floatと同じ方向のmargiが倍になる
解決方法
- そもそも同じ方向にmarginを設定しない(親要素のpaddingを利用する)
- 要素にdisplay: inline;を記述する
- marginの代わりにpaddingを使う
- IEハックを使ってIE6だけmarginを半分にする
2,後方互換モードの場合に親要素text-alignが子要素にも影響する
子要素にtext-align:left;を指定しましょう。
3,margin: 0 auto;でセンタリングレイアウトが効かない
解決方法
親要素にtext-align:center;を指定し、子要素にtext-align:left;を指定します。
#continer { width: auto; text-align: center; } #contents { width: 500px; margin: 0 auto; text-align:left; }
4,横に並べたリストが段々になってしまう
解決方法
li要素にfloat:left;かdisplay: inline;を指定する。
ul li { float: left; } ul li { display: inline; }
5,heightの指定が効かないバグ
解決方法
font-size:0;かoverflow:hidden;を指定する。
6,子要素にposition:relativeを指定した親要素のoverflow指定が効かない
解決方法
親要素にもposition:relative;を指定する。
7,ボックス要素のサイズにパディングやボーダーが含まれてしまう
解決方法
IE6向けのハックを使い、個別に値を指定します。
以下はスラッシュハックを利用した解決例です。
.sample { padding:50px; width:200px; /width: 300px; }
8,アンカーをdisplay:block;にした各リストアイテムの間にスペースができてしまう
解決方法
liに対しdisplay:block;を指定、またはアンカー要素にfloat: left; clear: left;を指定する。
ul li a { float: left; clear: left; } ul li a { display: inline; }
9,inputのsize属性が効かない
解決方法
CSSでwidthを指定する。
9,background-colorが指定された要素内にフロートがあると要素内の文字が消える
解決方法
フロートの親要素にはwidth指定をする。
10,left,topが指定されている要素でright, bottomが認識されない
解決方法
left,topとright, bottom同時指定しないこと。
11,overflow:hidden;が正しく効かない
解決方法
overflowを指定するときはwidth,heightを指定する。
12,z-indexの値が認識されない
解決方法
親要素にz-indexを指定していないと、親要素の出現順が優先されるため、親要素にもz-indexの指定を指定するか、出現順序を変えます。
13,画像の下に隙間ができる
解決方法
画像に対してvertical-align: bottom;を指定します。
14,画像を並べると横に隙間ができる
解決方法
改行やスペースが入っていると隙間ができます。
その他まだまだありますが、とりあえず気づいたものを紹介しました。
致命的なバグがあれば追記していきたいと思います。
参考:
IE6,7,8でHTML5を使う(Polyfill)
IE9.js
IE9.jsはIE6,7,8をIE9の動作に近づけてくれるライブラリです。
- html5shivと同機能のHTML5タグのCSS適用
- max-widthやmin-width
- CSSの直下の子セレクタの選択や隣接兄弟セレクタ、間接セレクタ、属性セレクタなどセレクタ系
- 複数クラスの指定
- opacityを使った透明度の指定
- 透過PNGの対応
- position:fixed;
- CSS3の疑似クラス
- アンカー要素以外の:hover
- :before,:afterなどの疑似要素
<!--[if lt IE 9]> <script src="http://ie7-js.googlecode.com/svn/version/2.1(beta4)/IE9.js"></script> <![endif]-->
何でもできるようになる最高のライブラリに思えますが、マイナス面のできなくなることもあるようです。
これらの詳しい利用方法について解説しているこちらの記事がオススメ:ie9.jsを使うと出来ること、出来なくなること。
html5shiv
html5shivというJavascriptライブラリはHTML5から新たに追加されたタグをIE6,7,8でも使えるようにするためのものです。
ダウンロードして以下のようにheadタグの中で読み込ませます。パフォーマンスを考慮してCSSより後に読み込ませるのが良いようです。
<!--[if lt IE 9]> <script src="dist/html5shiv.js"></script> <![endif]-->
参考サイト
IE6,7,8でCSS3を使う(Polyfill)
IE9.js
上記「IE6,7,8でHTML5を使う」でも紹介しましたが、IE9.jsを使うことでCSS3の疑似クラスを使うことができます。
その他のCSS2.1系の処理も補ってくれるので便利なライブラリですね。
CSS3 PIE
box-shadow, border-radius, border-image, background gradients, multiple background imagesをIE6,7,8でも利用できるようになるIE独自拡張のビヘイビアです。
ビヘイビアはこれ以外にも公開されているものが複数あります。
Selectivizr.js
Selectivizr.jsは読み込むだけでCSS3のセレクタ処理をIE6,7,8でエミュレートしてくれるライブラリです。
<script type="text/javascript" src="[JS library]"></script> <!--[if (gte IE 6)&(lte IE 8)]> <script type="text/javascript" src="selectivizr.js"></script> <noscript><link rel="stylesheet" href="[fallback css]" /></noscript> <![endif]-->
参考:
IE6,7,8でMedia Queries対応(Polyfill)
css3-mediaqueries-js
IE6,7,8はMedia Queriesに対応していませんが、「css3-mediaqueries-js」を読み込めば対応できるようです。
利用する際の注意点
- @media規則での利用のみに対応
- media typeを省略してはいけない
- @charsetを使わない
<!--[if lt IE 9]> <script src="http://css3-mediaqueries-js.googlecode.com/svn/trunk/css3-mediaqueries.js"></script> <![endif]-->
その他
css3-mediaqueries-js以外にもrespond.jsというライブラリがあります。
参考:
IE6でPNG対応
DD_belatedPNG
DD_belatedPNGはIE6でPNGの透過表示を実現するためのライブラリです。
<!--[if IE 6]> <script src="js/DD_belatedPNG.js"></script> <script> DD_belatedPNG.fix('img, .png_background'); </script> <![endif]-->
jQuery.belatedPNG.js
上記の「DD_belatedPNG」をjQueryPlugin化したものです。
より使いやすく、いくつかの問題も解決しているそうです。
$("selector").fixPng();
参考:
IE6,7,8でSVG
Raphaël
SVGをそのまま使うことはできませんがIE6でも高い再現度のライブラリです。
過去に一度利用しましたが、実感としてCanvasのように利用できます。
SIE
SVG形式の画像を表示できるJavaScriptライブラリのようです。
調べ切れていないので、一部候補となる解決案を紹介しています。
IE6,7,8でCanvas
ExplorerCanvas
以下のようにjsを読み込むだけで利用できるようです。
<head> <!--[if IE]><script src="excanvas.js"></script><![endif]--> </head>
調べ切れていないので、一部候補となる解決案を紹介しています。
IE6,7,8でVideoタグ
html5media
読み込むだけで利用できるようになるようです。
<head> <script src="http://api.html5media.info/1.1.5/html5media.min.js"></script> </head>
IE6,7でWeb Font
クロスブラウザでWebフォントを利用するためには、最低2つの形式が必要です。
1つは、Internet ExplorerのためにEOT(.eot)形式、2つめはその他の主要ブラウザに対してTrueType(.ttf)かOpenType(.otf)形式を用意すれば、問題なさそうです。
参考:
まとめ
最後力尽きました。
また調べて追記していきたいと思います。はやくIEを気にせずWeb制作ができる日が来ないかな~なんて夢のまた夢ですがこれからもうまく付き合っていきたいですね。ちなみにWebkitさんが好きです。
クラスメソッドアドベントカレンダー2012 25日6本目でした。
Merry Christmas!